package com.towexin.config.mylogging;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.towexin.application.system.domain.SystemLog;
import com.towexin.application.system.domain.User;
import com.towexin.application.system.service.SystemLogService;
import com.towexin.application.system.service.UserService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * TODO
 * 日志记录切面
 * @author Towexin
 * @version 1.0
 * @date 2021/4/18 10:03
 */
@Aspect
@Component
public class SystemLogAspect {

    /**我这里是使用log4j2把一些信息打印在控制台上面，可以不写 */
    private static final Logger log = LogManager.getLogger(SystemLogAspect.class);

    /**操作数据库 */
    @Autowired
    private SystemLogService systemLogService;

    @Autowired
    private UserService userService;

    //定义切点 @Pointcut
    //在注解的位置切入代码
    @Pointcut("@annotation(MyLog)")
    public void logPoinCut() {
    }

    //切面 配置通知
    @Before("logPoinCut()")         //AfterReturning
    public void saveOperation(JoinPoint joinPoint) {
        log.info("---------------接口日志记录---------------");
        //用于保存日志
        SystemLog systemLog = new SystemLog();

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        systemLog.setMethod(className + "." + methodName);

        //获取操作--方法上的Log的值
        MyLog myLog = method.getAnnotation(MyLog.class);
        if (myLog != null) {
            //保存操作事件
            String operation = myLog.operation();
            systemLog.setOperation(operation);

            //保存日志类型
            systemLog.setType(myLog.type().getKey());

            // 操作人账号、姓名（需要提前将用户信息存到session）
            try {
                if (myLog.type().getKey()!=0){
                    systemLog.setUsername(SecurityUtils.getSubject().getPrincipal().toString());
                }else {
                    if (userService.count(new QueryWrapper<User>().eq("username", joinPoint.getArgs()[0].toString()))==0){
                        log.info("******用户不存在，不记录登录日志******");
                        return;
                    }
                    systemLog.setUsername(joinPoint.getArgs()[0].toString());
                }
            }catch (Exception e){
                e.printStackTrace();
            }

            log.info("operation="+operation+",type="+myLog.type().getKey());
        }

        //请求的参数
        //Object[] args = joinPoint.getArgs();
        //if (args.length == 0) {
        //    systemLog.setParams(null);
        //} else {
        //    for (Object arg:args){
        //        if (arg instanceof MultipartFile){
        //            systemLog.setParams("文件名称："+((MultipartFile)args[0]).getOriginalFilename());
        //            break;
        //        }else {
        //            systemLog.setParams(JSON.toJSONString(arg));
        //            break;
        //        }
        //    }
        //    //if (systemLog.getMethod().equals("com.towexin.system.controller.FileUploadController.upload")){
        //    //    systemLog.setParams("文件名称："+((MultipartFile)args[0]).getOriginalFilename());
        //    //}else {
        //    //    systemLog.setParams(JSON.toJSONString(args));
        //    //}
        //}

        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String requestURL = request.getRequestURL().toString();
        systemLog.setUrl(requestURL);
        // 客户端ip
        String ip = request.getRemoteAddr();
        systemLog.setIp(ip);

        log.info("URL="+requestURL,"IP="+ip);

        //调用service保存Operation实体类到数据库
        //我id使用的是UUID，不需要的可以注释掉
        systemLogService.save(systemLog);
    }
}
